import { Injectable, ForbiddenException, HttpException, HttpStatus } from '@nestjs/common'
import { UserService } from '@/modules/user/user.service'
import { ConfigService } from '@nestjs/config'
import { JwtService } from '@nestjs/jwt'
import { isEmpty } from 'lodash'
import { ResultData } from '@/utils/result'
import { GenerateUUID } from '@/utils/index'
import { ErrorEnum } from '@/constants/error-code.constant'
import { LoginDto } from './dto/index'
import { RedisService } from '@/modules/redis/redis.service'
import { RedisKeys } from '@/constants/cache.constant'
import { genCaptchaImgKey, genAuthTokenKey } from '@/utils/genKey'
import * as CryptoJS from 'crypto-js'

@Injectable()
export class AuthService {
	constructor(
		private readonly jwtService: JwtService,
		private readonly userService: UserService,
		private readonly configService: ConfigService,
		private readonly redisService: RedisService
	) {}

	async login(loginDto: LoginDto) {
		// 验证码验证
		const captchaValidated = await this.checkImgCaptcha(loginDto.code, loginDto.captchaKey)

		if (!captchaValidated) return ResultData.fail(ErrorEnum.INVALID_VERIFICATION_CODE)
		// 用户验证
		const user = await this.checkUser(loginDto.username, loginDto.password)
		if (isEmpty(user)) return ResultData.fail(ErrorEnum.USER_NOT_FOUND)
		// 生成token
		const uuid = GenerateUUID()
		const accessToken = await this.jwtService.sign({
			uuid,
			sub: user.id, // 用户id 用 sub 来保存与 JWT 标准保持一致
			roles: user.roles,
		})
		await this.redisService.setString(genAuthTokenKey(user.id), accessToken, 1000 * 60 * 5)
		return ResultData.success({ accessToken })
	}
	/**
	 * 校验图片验证码
	 */
	async checkImgCaptcha(loginCode: string, uuid: string) {
		const captchaEnabled = await this.configService.get<boolean>('app.captchaEnabled')
		const captchaImgKey = genCaptchaImgKey(uuid)
		if (captchaEnabled) {
			const code = await this.redisService.getString(captchaImgKey)
			if (!code || !loginCode || code !== loginCode.toLowerCase()) {
				return false
			}
		}
		// 校验成功后移除验证码
		await this.redisService.del(captchaImgKey)
		return true
	}
	/**
	 * 校验用户
	 */
	async checkUser(username: string, pass: string): Promise<any> {
		const user = await this.userService.findOne(username)
		const AESSecretKey = await this.configService.get<string>('app.AESSecretKey')
		const password = CryptoJS.AES.decrypt(pass, CryptoJS.enc.Base64.parse(AESSecretKey), {
			mode: CryptoJS.mode.ECB,
			padding: CryptoJS.pad.Pkcs7,
			length: 128,
		}).toString(CryptoJS.enc.Utf8)

		console.log('password---', AESSecretKey, password)
		// 校验密码是否正确
		if (user && user.password === password) {
			const { password, ...result } = user
			return result
		}
		return null
	}
	/**
	 * 从令牌中获取数据声明
	 *
	 * @param token 令牌
	 * @return 数据声明
	 */
	parseToken(token: string) {
		if (!token) return null
		const payload = this.jwtService.verify(token)
		return payload
	}
}
